//
//  EVEAPICharacterSheet.m
//  EVE Mac Suite
//
//  Created by Vadim Lozko on 2/13/09.
//  Copyright 2009 __Vadim__. All rights reserved.
//

#import "EVEAPICharacterSheet.h"
#import "EVEAPICoreDataController.h"
#import "EVECDCharacter.h"
#import "EVECDLearnedSkill.h"
#import "EVECDLearnedGroup.h"
#import "EVECDSkillGroup.h"
#import "EVECDSkill.h"
#import "EVECDCharismaEnhancer.h"
#import "EVECDIntelligenceEnhancer.h"
#import "EVECDMemoryEnhancer.h"
#import "EVECDPerceptionEnhancer.h"
#import "EVECDWillpowerEnhancer.h"

@implementation EVEAPICharacterSheet

@synthesize managedObjectCharacter;

-(void)dealloc
{
	if(managedObjectCharacter)
	{
		[managedObjectCharacter release];
	}
	[super dealloc];
}

#pragma mark EVEAPIDataHandler protocol methods

-(NSString*)xmlStorePath
{
	return [[super xmlStorePath] stringByAppendingString:@" - CharacterSheet.xml"];
}

-(NSString*)APIDocumentType
{
	return CHARACTER_SHEET_API_TYPE;
}

-(void)postWillUpdateCoreDataStoreNotification
{
	NSDictionary* userInfo = [NSDictionary dictionaryWithObject:[self charName] forKey:CHAR_INFO_DICT_NAME];
	[[NSNotificationCenter defaultCenter] postNotificationName:WILL_UPDATE_LEARNED_SKILLS_NOTIFICATION_NAME object:self userInfo:userInfo];
}

-(void)update
{
	[self forceUpdate];
}

-(void)initializeCharacterSkills
{
	NSSet* allSkillGroups = [EVECDContext fetchObjectsForEntityName:@"EVECDSkillGroup" withPredicate:nil];
	for(EVECDSkillGroup* group in allSkillGroups)
	{
		EVECDLearnedGroup* learnedGroup = [NSEntityDescription insertNewObjectForEntityForName:@"EVECDLearnedGroup" 
																		inManagedObjectContext:EVECDContext];
		learnedGroup.group = group;
		learnedGroup.learnedBy = managedObjectCharacter;
		for(EVECDSkill* skill in group.containsSkills)
		{
			EVECDLearnedSkill* learnedSkill = [NSEntityDescription insertNewObjectForEntityForName:@"EVECDLearnedSkill"
																			inManagedObjectContext:EVECDContext];
			learnedSkill.partOfLearnedGroup = learnedGroup;
			learnedSkill.skill = skill;
		}
	}
}

-(void)updateCoreDataStore
{
	//[self performSelectorOnMainThread:@selector(postWillUpdateCoreDataStoreNotification) withObject:nil waitUntilDone:YES];
	[self postWillUpdateCoreDataStoreNotification];
#ifdef DEBUG
	NSLog(@"Creating basic character info");
#endif
	NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
	//[EVECDContext lock];
	//[[EVEAPICoreDataController coreDataController] performSelectorOnMainThread:@selector(lockContext) withObject:nil waitUntilDone:YES];
	NSPredicate* nameSearchPredicate = [NSPredicate predicateWithFormat:@"name like %@", [self charName]];
	managedObjectCharacter = (EVECDCharacter*)[EVECDContext fetchObjectForEntityName:@"EVECDCharacter" 
																	   withPredicate:nameSearchPredicate];
	if(!managedObjectCharacter)
	{
		self.managedObjectCharacter = [NSEntityDescription insertNewObjectForEntityForName:@"EVECDCharacter" 
																	inManagedObjectContext:EVECDContext];
		[self initializeCharacterSkills];
	}
	_didStartSkillsRowset = NO;
	NSXMLParser* parser = [[NSXMLParser alloc] initWithData:[xmlDoc XMLData]];
	parser.delegate = self;
	[parser parse];
	
	NSPredicate* learningSkillNamePredicate = [NSPredicate predicateWithFormat:@"skill.name like 'Learning'"];
	NSPredicate* characterNamePredicate = [NSPredicate predicateWithFormat:@"partOfLearnedGroup.learnedBy.name like %@",
										   managedObjectCharacter.name];
	NSPredicate* learningSkillPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:
										   [NSArray arrayWithObjects:learningSkillNamePredicate, characterNamePredicate, nil]];
	EVECDLearnedSkill* learningSkill = (EVECDLearnedSkill*)[EVECDContext fetchObjectForEntityName:@"EVECDLearnedSkill" 
																					withPredicate:learningSkillPredicate];
	if(learningSkill)
	{
		NSArray* attributeNames = [NSArray arrayWithObjects:@"intelligence", @"memory", @"perception", @"willpower", @"charisma", nil];
		int learningLevel = learningSkill.level.intValue;
		for(NSString* attributeName in attributeNames)
		{
			double newAttributeValue = ([[managedObjectCharacter valueForKey:attributeName] doubleValue] * (1 + (learningLevel * .02)));
			[managedObjectCharacter setValue:[NSNumber numberWithDouble:newAttributeValue] forKey:attributeName];
		}
	}
	//[EVECDContext unlock];
	//[[EVEAPICoreDataController coreDataController] performSelectorOnMainThread:@selector(unlockContext) withObject:nil waitUntilDone:YES];
	//[self performSelectorOnMainThread:@selector(updateDidFinish:) withObject:(NSNumber*)kCFBooleanTrue waitUntilDone:NO];
	[self updateDidFinish:(NSNumber*)kCFBooleanTrue];
	[pool release];
}

-(void)verifyCoreDataStore
{
	//Do a search for skills. Any amount > 0 would be considered valid
	NSPredicate* verifySkillsPredicate = [NSPredicate predicateWithFormat:@"name like %@", 
										  [initialCharacterInfo objectForKey:CHAR_INFO_DICT_NAME]];
	EVECDCharacter* character = (EVECDCharacter*)[EVECDContext fetchObjectForEntityName:@"EVECDCharacter" withPredicate:verifySkillsPredicate];
	if(!character)
	{
		//[NSThread detachNewThreadSelector:@selector(updateCoreDataStore) toTarget:self withObject:nil];
		[self updateCoreDataStore];
	} else {
		managedObjectCharacter = character;
		[self updateDidFinish:(NSNumber*)kCFBooleanTrue];
	}
}

-(void)documentDidDownload:(BOOL)success;
{
	if([delegate respondsToSelector:@selector(characterSheetXMLDownloadDidFinish:)])
	{
		[delegate characterSheetXMLDownloadDidFinish:success];
	}
}

-(void)downloadRequestDidFailWithError:(NSError*)error
{
	managedObjectCharacter = (EVECDCharacter*)[EVECDContext fetchObjectForEntityName:@"EVECDCharacter" 
																	   withPredicate:@"name like %@", [self charName]];
	[super downloadRequestDidFailWithError:error];
}

-(NSTimer*)updateTimer
{
	return updateTimer;
}

@end

@implementation EVEAPICharacterSheet (ParseDelegate)

-(void)parserDidStartDocument:(NSXMLParser*)parser
{
	//[EVECDContext lock];
	managedObjectCharacter.memory = [NSNumber numberWithDouble:0];
	managedObjectCharacter.intelligence = [NSNumber numberWithDouble:0];
	managedObjectCharacter.charisma = [NSNumber numberWithDouble:0];
	managedObjectCharacter.perception = [NSNumber numberWithDouble:0];
	managedObjectCharacter.willpower = [NSNumber numberWithDouble:0];
	//[EVECDContext unlock];
	[super parserDidStartDocument:parser];
}

-(void)parser:(NSXMLParser*)parser 
didStartElement:(NSString*)elementName
 namespaceURI:(NSString*)namespaceURI 
qualifiedName:(NSString*)qualifiedName 
   attributes:(NSDictionary*)attributeDict
{
	//[EVECDContext lock];
	if([elementName isEqualToString:@"memoryBonus"])
	{
		attributeEnhancer = [[NSEntityDescription insertNewObjectForEntityForName:@"EVECDMemoryEnhancer"
														   inManagedObjectContext:EVECDContext] retain];
		managedObjectCharacter.memoryEnhancer = (EVECDMemoryEnhancer*)attributeEnhancer;
	}
	else if([elementName isEqualToString:@"intelligenceBonus"])
	{
		attributeEnhancer = [[NSEntityDescription insertNewObjectForEntityForName:@"EVECDIntelligenceEnhancer"
														   inManagedObjectContext:EVECDContext] retain];
		managedObjectCharacter.intelligenceEnhancer = (EVECDIntelligenceEnhancer*)attributeEnhancer;
	}
	else if([elementName isEqualToString:@"charismaBonus"])
	{
		attributeEnhancer = [[NSEntityDescription insertNewObjectForEntityForName:@"EVECDCharismaEnhancer"
														   inManagedObjectContext:EVECDContext] retain];
		managedObjectCharacter.charismaEnhancer = (EVECDCharismaEnhancer*)attributeEnhancer;
	}
	else if([elementName isEqualToString:@"perceptionBonus"])
	{
		attributeEnhancer = [[NSEntityDescription insertNewObjectForEntityForName:@"EVECDPerceptionEnhancer"
														   inManagedObjectContext:EVECDContext] retain];
		managedObjectCharacter.perceptionEnhancer = (EVECDPerceptionEnhancer*)attributeEnhancer;
	}
	else if([elementName isEqualToString:@"willpowerBonus"])
	{
		attributeEnhancer = [[NSEntityDescription insertNewObjectForEntityForName:@"EVECDWillpowerEnhancer"
														   inManagedObjectContext:EVECDContext] retain];
		managedObjectCharacter.willpowerEnhancer = (EVECDWillpowerEnhancer*)attributeEnhancer;
	}
	else if([elementName isEqualToString:@"rowset"])
	{
		if([[attributeDict objectForKey:@"name"] isEqualToString:@"skills"])
		{
			_didStartSkillsRowset = YES;
		}
	}
	else if([elementName isEqualToString:@"row"])
	{
		if(_didStartSkillsRowset)
		{
			NSPredicate* skillIDPredicate = [NSPredicate predicateWithFormat:@"skill.id == %@", 
											 [NSNumber numberWithInt:[[attributeDict objectForKey:@"typeID"] intValue]]];
			NSPredicate* characterNamePredicate = [NSPredicate predicateWithFormat:@"partOfLearnedGroup.learnedBy.name like %@", 
												   managedObjectCharacter.name];
			NSPredicate* learnedSkillPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:
												  [NSArray arrayWithObjects:skillIDPredicate, characterNamePredicate, nil]];
			EVECDLearnedSkill* learnedSkill = (EVECDLearnedSkill*)[EVECDContext fetchObjectForEntityName:@"EVECDLearnedSkill" 
																						   withPredicate:learnedSkillPredicate];
			learnedSkill.skillPointsLearned = [NSNumber numberWithInt:[[attributeDict objectForKey:@"skillpoints"] intValue]];
			learnedSkill.currentlyInTraining = (NSNumber*)kCFBooleanFalse;
			NSString* learnedSkillName = learnedSkill.skill.name;
			if([learnedSkillName isEqualToString:@"Analytical Mind"] || [learnedSkillName isEqualToString:@"Logic"])
			{
				managedObjectCharacter.intelligence = 
				[NSNumber numberWithDouble:(managedObjectCharacter.intelligence.doubleValue + learnedSkill.level.intValue)];
			}
			else if([learnedSkillName isEqualToString: @"Eidetic Memory"] || [learnedSkillName isEqualToString:@"Instant Recall"])
			{
				managedObjectCharacter.memory = 
				[NSNumber numberWithDouble:(managedObjectCharacter.memory.doubleValue + learnedSkill.level.intValue)];
			}
			else if([learnedSkillName isEqualToString:@"Clarity"] || [learnedSkillName isEqualToString:@"Spatial Awareness"])
			{
				managedObjectCharacter.perception = 
				[NSNumber numberWithDouble:(managedObjectCharacter.perception.doubleValue + learnedSkill.level.intValue)];
			}
			else if([learnedSkillName isEqualToString:@"Focus"] || [learnedSkillName isEqualToString:@"Iron Will"])
			{
				managedObjectCharacter.willpower = 
				[NSNumber numberWithDouble:(managedObjectCharacter.willpower.doubleValue + learnedSkill.level.intValue)];
			}
			else if([learnedSkillName isEqualToString:@"Empathy"] || [learnedSkillName isEqualToString:@"Presence"])
			{
				managedObjectCharacter.charisma = 
				[NSNumber numberWithDouble:(managedObjectCharacter.charisma.doubleValue + learnedSkill.level.intValue)];
			}
		}
	}
	//[EVECDContext unlock];
	self.currentCharacters = @"";
}

- (void)parser:(NSXMLParser*)parser foundCharacters:(NSString*)string
{
	self.currentCharacters = [self.currentCharacters stringByAppendingString:string];
}

- (void)parser:(NSXMLParser*)parser 
 didEndElement:(NSString*)elementName
  namespaceURI:(NSString*)namespaceURI
 qualifiedName:(NSString*)qName
{
	//[EVECDContext lock];
	if([elementName isEqualToString:@"name"])	
	{
		managedObjectCharacter.name = self.currentCharacters;
	}
	else if([elementName isEqualToString:@"race"])
	{
		managedObjectCharacter.race = self.currentCharacters;
	}
	else if([elementName isEqualToString:@"bloodLine"])
	{
		managedObjectCharacter.bloodline = self.currentCharacters;
	}
	else if([elementName isEqualToString:@"gender"])
	{
		managedObjectCharacter.gender = self.currentCharacters;
	}
	else if([elementName isEqualToString:@"corporationName"])
	{
		managedObjectCharacter.corporation = self.currentCharacters;}
	else if([elementName isEqualToString:@"cloneName"])
	{
		managedObjectCharacter.cloneName = self.currentCharacters;}
	else if([elementName isEqualToString:@"cloneSkillPoints"])
	{
		managedObjectCharacter.cloneSkillPoints = [NSNumber numberWithLongLong:[self.currentCharacters longLongValue]];
	}
	else if([elementName isEqualToString:@"balance"])
	{	
		managedObjectCharacter.balance = [NSNumber numberWithDouble:[self.currentCharacters doubleValue]];
	}
	else if([elementName isEqualToString:@"augmentatorName"])
	{
		attributeEnhancer.augmentatorName = self.currentCharacters;
	}
	else if([elementName isEqualToString:@"augmentatorValue"])
	{
		attributeEnhancer.augmentatorValue = [NSNumber numberWithInt:[self.currentCharacters intValue]];
	}
	else if([elementName isEqualToString:@"memoryBonus"])
	{
		int newAttributeValue = managedObjectCharacter.memory.intValue + attributeEnhancer.augmentatorValue.intValue;
		managedObjectCharacter.memory = [NSNumber numberWithInt:newAttributeValue];
		[attributeEnhancer release];
	} 
	else if([elementName isEqualToString:@"intelligenceBonus"])
	{
		managedObjectCharacter.intelligence = 
		[NSNumber numberWithDouble:(managedObjectCharacter.intelligence.doubleValue + attributeEnhancer.augmentatorValue.intValue)];
		[attributeEnhancer release];
	}
	else if([elementName isEqualToString:@"charismaBonus"])
	{
		managedObjectCharacter.charisma = 
		[NSNumber numberWithDouble:(managedObjectCharacter.charisma.doubleValue + attributeEnhancer.augmentatorValue.intValue)];
		[attributeEnhancer release];
	}
	else if([elementName isEqualToString:@"perceptionBonus"])
	{
		managedObjectCharacter.perception = 
		[NSNumber numberWithDouble:(managedObjectCharacter.perception.doubleValue + attributeEnhancer.augmentatorValue.intValue)];
		[attributeEnhancer release];
	}
	else if([elementName isEqualToString:@"willpowerBonus"])
	{
		managedObjectCharacter.willpower = 
		[NSNumber numberWithDouble:(managedObjectCharacter.willpower.doubleValue + attributeEnhancer.augmentatorValue.intValue)];
		[attributeEnhancer release];
	}
	else if([elementName isEqualToString:@"intelligence"])
	{
		NSNumber* intelligenceValue = [NSNumber numberWithInt:[self.currentCharacters intValue]];
		managedObjectCharacter.intelligence = 
		[NSNumber numberWithDouble:(managedObjectCharacter.intelligence.doubleValue + intelligenceValue.intValue)];
		managedObjectCharacter.baseIntelligence = intelligenceValue;
	} 
	else if([elementName isEqualToString:@"memory"])
	{
		NSNumber* memoryValue = [NSNumber numberWithInt:[self.currentCharacters intValue]];
		managedObjectCharacter.memory = 
		[NSNumber numberWithDouble:(managedObjectCharacter.memory.doubleValue + memoryValue.intValue)];;
		managedObjectCharacter.baseMemory = memoryValue;
	}
	else if([elementName isEqualToString:@"charisma"])
	{
		NSNumber* charismaValue = [NSNumber numberWithInt:[self.currentCharacters intValue]];
		managedObjectCharacter.charisma = 
		[NSNumber numberWithDouble:(managedObjectCharacter.charisma.doubleValue + charismaValue.intValue)];
		managedObjectCharacter.baseCharisma = charismaValue;
	}
	else if([elementName isEqualToString:@"perception"])
	{
		NSNumber* perceptionValue = [NSNumber numberWithInt:[self.currentCharacters intValue]];
		managedObjectCharacter.perception = 
		[NSNumber numberWithDouble:(managedObjectCharacter.perception.doubleValue + perceptionValue.intValue)];
		managedObjectCharacter.basePerception = perceptionValue;
	}
	else if([elementName isEqualToString:@"willpower"])
	{
		NSNumber* willpowerValue = [NSNumber numberWithInt:[self.currentCharacters intValue]];
		managedObjectCharacter.willpower = 
		[NSNumber numberWithDouble:(managedObjectCharacter.willpower.doubleValue + willpowerValue.intValue)];
		managedObjectCharacter.baseWillpower = willpowerValue;
	}
	else if([elementName isEqualToString:@"rowset"])
	{
		if(_didStartSkillsRowset)
		{
			_didStartSkillsRowset = NO;
		}
	}
	//[EVECDContext unlock];
}

@end

